package interceptcrossing;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Collection;

/**
 * Статус заметающей прямой
 *
 * @author Igor Botyan
 */
public class SweptLineStatus {

	List<Intercept> intercepts;

	Point point;

	/**
	 * Создание статуса заметающей прямой
	 */
	public SweptLineStatus() {
		this.intercepts = new LinkedList<Intercept>();
	}

	/**
	 * Добавление отрезка в структуру данных
	 *
	 * @param intercept отрезок
	 */
	public void add(Intercept intercept) {
		this.intercepts.add(intercept);
	}

	/**
	 * Удаление отрезка из структуры данных
	 *
	 * @param intercept отрезок
	 */
	public void remove(Intercept intercept) {
		this.intercepts.remove(intercept);
	}

	/**
	 * Очистка структуры данных
	 */
	public void clear() {
		this.intercepts.clear();
	}

	public void setPoint(Point point) {
		this.point = point;
	}

	/**
	 * Получение отрезка, находящегося непосредственно выше заданного
	 *
	 * @param intercept заданный отрезок
	 * @return nотрезок, находящийся непосредственно выше заданного, или null
	 */
	public Intercept getAbove(Intercept intercept, Abscissa point) {
		if (intercepts.isEmpty())
			return null;
		double distance = Double.MAX_VALUE;
		Intercept above = null;

		for (Intercept currIntercept : intercepts) {
			if (currIntercept.isAbove(intercept, point.x)) {
				double curr = intercept.getAboveDistance(currIntercept, point.x);

				if ((curr < distance) || (above == null)) {
					above = currIntercept;
					distance = curr;
				}
			}
		}

		return above;
	}

	public Collection<Intercept> getAllAbove(Intercept intercept, Abscissa point) {
		Collection<Intercept> ret = new LinkedList<Intercept>();

		for (Intercept currIntercept : intercepts) {
			if (currIntercept.isAbove(intercept, point.x)) {
				ret.add(currIntercept);
			}
		}

		return ret;
	}

	public Collection<Intercept> getAllUnder(Intercept intercept, Abscissa point) {
		Collection<Intercept> ret = new LinkedList<Intercept>();

		for (Intercept currIntercept : intercepts) {
			if (intercept.isAbove(currIntercept, point.x)) {
				ret.add(currIntercept);
			}
		}

		return ret;
	}

	/**
	 * Получение отрезка, находящегося непосредственно ниже заданного
	 *
	 * @param intercept заданный отрезок
	 * @return nотрезок, находящийся непосредственно ниже заданного, или null
	 */
	public Intercept getUnder(Intercept intercept, Abscissa point) {
		if (intercepts.isEmpty())
			return null;

		double distance = Double.MAX_VALUE;
		Intercept under = null;
		for (Iterator<Intercept> iter = intercepts.iterator(); iter.hasNext();) {
			Intercept currIntercept = (Intercept) iter.next();
			if (currIntercept.isBelow(intercept, point.x)) {
				double curr = (intercept.getBelowDistance(currIntercept, point.x));
				if ((curr < distance) || (under == null)) {
					under = currIntercept;
					distance = curr;
				}
			}
		}
		return under;
	}
}
